<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>JavaScript 代码片段</title>
</head>
<body>
	<script>
		/**
		 * 1
		 * 使用递归,对于给定字符串中的每个字母，为字母创建字谜。
		 * 使用map()将字谜与每部分字谜组合
		 * 然后使用reduce() 将所有字谜组合到一个数组中
		 * 最基本情况是字符串长度等于2或1.
		 */
		const anagrams = str => {
			if(str.length <= 2){
				return str.length === 2 ? [str,str[1]+str[0]] : [str];
			}
			return str.split('').reduce((acc,letter,i) => acc.concat(anagrams(str.slice(0,i) + str.slice(i + 1)).map(val => letter + val)),[]);
		};
		console.log(anagrams("abc"))
		//->["abc", "acb", "bac", "bca", "cab", "cba"]
		

		/**
		 * 2
		 * 数组平均数
		 * 使用reduce()将每个值添加到累加器
		 * 初始值为0,总和除以数组长度
		 */
		const average = arr => {
			return arr.reduce((acc,val) => acc + val, 0)/arr.length;
		} 
		console.log(average([1,2,3,4]));//->2.5


		/**
		 * 3
		 * 大写每个单词的首字母
		 * 使用replace()匹配每个单词的第一个字符
		 * 并使用toUpperCase()将其大写
		 */
		const capitalizeEW = str => {
			return str.replace(/\b[a-z]/g,char =>{
				return char.toUpperCase();
			});
		}
		console.log(capitalizeEW('hello world!'))
		//-> Hello World!
		
		/**
		 * 4
		 * 首字母大写
		 * 使用slice(0,1)和toUpperCase()大写第一个字母
		 * slice(1)获取字符串的其余部分不变
		 * 获将其设置为true以转换小写
		 * (注意：和上一个示例不是同一个事件)
		 */
		const capitalize = (str,lowerRest = false) => {
			return str.slice(0,1).toUpperCase() + (lowerRest ? str.slice(1).toLowerCase() : str.slice(1));
		}
		console.log(capitalize('myName',true))
		//-> Myname
		
		/**
		 * 5
		 * 检查回文
		 * 将字符串转换为toLowerCase()
		 * 并使用replace()从中删除非字母的字符
		 * 然后将其转换为tolowerCase(),将('')拆分为单独字符
		 * reverse(),join(),与原始的非反转字符进行比较,然后将其转换为tolwerCase()
		 */
		const palindrome = str => {
			const s = str.toLowerCase().replace(/[\W_]/g,'');
			return s === s.split('').reverse().join('');
		}
		console.log(palindrome('taco cat'))//-> true


		/**
		 * 6
		 * 计算数组中值得出现次数
		 * 每次遇到数组中的特定值时
		 * 使用reduce()来递增计数器
		 */
		const countOccurences = (arr,value) => {
			return arr.reduce((a,v)=> {
				return v === value ? a + 1 : a + 0
			},0)
		}
		console.log(countOccurences([1,2,1,4,1,2,1,4,3],2))//-> 2

		/**
		 * 7
		 * 获取当前URL
		 * 使用window.location.href来获取当前URL
		 */
		const currentUrl = _ => {
			return window.location.href;
		}
		console.log(currentUrl())//-> 当前URL

		/**
		 * 8
		 *Deep flatten array深平数组
		 *使用递归 使用reduce()来获取所有不是数组的元素
		 *flatten每个元素都是数组
		 */
		const deepFlatten = arr => {
			return arr.reduce((a,v)=> a.concat(Array.isArray(v) ? deepFlatten(v) : v),[]
			);
		}
		console.log(deepFlatten([1,[2],[[3,[12]],4],5]))
		//-> [1, 2, 3, 4, 5]
		
		/**
		 * 9
		 * 数组之间的区别
		 * 从b创建一个Set，然后在a上使用Array.filter()
		 * 只保留b中不包含的值
		 */
		const difference = (a,b) => {
			const s = new Set(b);
			return a.filter(x => !s.has(x));
		}
		console.log(difference([1,2,3],[1,3])) //-> [2]


		/**
		 * 10
		 * 是否可以按整数整除
		 * 使用模块运算% 来检查余数是否等于0
		 */
		const isDivisible = (dn,dr) => dn % dr === 0;
		console.log(isDivisible(6,3))//-> true


		/**
		 * 11
		 * 奇数和偶数
		 * 使用Math.abs()将逻辑扩展为负数
		 * 使用模%运算符进行检查
		 * 如果数字是偶数返回true,奇数返回false
		 */
		const isEven = num => num % 2 ===0;
		console.log(isEven(3))//-> false



		/**
		 * 12
		 * 阶乘
		 * 使用递归，如果n小于或等于1，则返回1
		 * 否则返回n和n-1的阶乘的乘积
		 */
		const factorial = n => n <= 1 ? 1 : n * factorial(n-1);
		console.log(factorial(6))//-> 720




		/**
		 * 12
		 * 菲波那切数组生成器
		 * 创建一个特定长度的空数组
		 * 初始化前两个值(0和1)
		 * 使用Array.reduce()向数组中添加值
		 * 后面的一个数等于前面两个数相加之和(前两个除外)
		 */
		const fibonacci = n =>{
			return Array(n).fill(0).reduce((acc,val,i) => acc.concat(i > 1 ? acc[i-1]+acc[i-2] : i),[])
		}
		console.log(fibonacci(5)) //->  [0, 1, 1, 2, 3]



		/**
		 * 13
		 * 过滤数组中的非唯一值
		 * 将Array.filter()用于仅包含唯一值得数组
		 */
		const filterNonUnique = arr => {
			return arr.filter(i=>{
				return arr.indexOf(i) === arr.lastIndexOf(i);
			})
		}
		console.log(filterNonUnique([1,2,2,3,4,4,5]))
		// -> [1, 3, 5]	
		


		/**
		 * 14
		 * Flatten数组
		 * 使用reduce()来获取数组中的所有元素
		 * 并使用concat()来使他们flatten
		 */
		const flatten = arr => arr.reduce((a,v) => a.concat(v),[]);
		console.log(flatten([1,[2],3,4,[5]]))//-> [1, 2, 3, 4, 5]



		/**
		 * 15
		 * 从数组中获取最大值
		 * 使用Math.max()与spreaad运算符(...)
		 * 结合得到数组中的最大值
		 */
		const arrayMax = arr => Math.max(...arr);
		console.log(arrayMax([10,2,6])) //-> 10



		/**
		 * 16
		 * 从数组中获取最小值
		 * 使用Math.min()与spread运算符(...)
		 * 结合得到数组中的最小值
		 */
		const arrayMin = arr => Math.min(...arr);
		console.log(arrayMin([10,2,6])) //-> 2




		/**
		 * 17
		 * 获取滚动位置
		 * 如果已定义 请使用pageXOffset和pageYOffset
		 * 否则使用scrllLeft和scrollTop
		 * 可以省略el来使用window的默认值
		 */
		const getScrollPos = (el = window) => {
			return ({
				x : (el.pageXOffset !== undefined) ? el.pageXOffset : el.scrollLeft,
				y : (el.pageYOffset !== undefined) ? el.pageYOffset : el.scrollTop
 			})
		}
		console.log(getScrollPos()) //-> {x: 0, y: 0}


		/**
		 * 18
		 * 用range初始化数组
		 * 使用Array(emd-start) 创建所需要长度的数组
		 * 使用map()来填充范围中的所需值
		 * 可以省略start使用默认值0；
		 */
		const initArray = (end,start=0) => {
			return Array.apply(null,Array(end - start)).map((v,i) => i + start);
		}
		console.log(initArray(3)) //-> [0, 1, 2]




		/**
		 * 19
		 * 用值初始化数组
		 * 使用Array(n) 创建所需要长度的数组
		 * fill(v)以填充所需要的值
		 * 可以忽略value使用默认值0
		 */
		const initializeArray = (n,value = 0) => Array(n).fill(value);
		console.log(initializeArray(5,2))//-> [2, 2, 2, 2, 2]


		/**
		 * 20
		 * 返回列表的第一和最后
		 * 第一arr[0]
		 * 最后arr.slice(-1)[0]
		 */
		const head = arr => arr[0];
		console.log(head([1,2,3])) //-> 1
		const last = arr => arr.slice(-1)[0];
		console.log(last([1,2,3])) //-> 3


		/**
		 * 21
		 * 来自键值对的对象
		 * 使用Array.reduce()创建和组合键值对
		 */
		const objFromPairs = arr => {
			return arr.reduce((a,v) => (a[v[0]] = v[1],a),{})
		}
		console.log(objFromPairs([['a',1],['b',2]]))
		// -> {a: 1, b: 2}
		


		/**
		 * 22
		 * 1、范围内的随机整数
		 * 2、范围内的随机数(小数)
		 * 使用Math.random()生成
		 * 使用Math.floor()成为整数
		 */
		const random = (min,max) => {
			return Math.floor(Math.random()*(max-min+1)) + min;
		}
		console.log(random(0,5))//->0-5

		const randoms = (min,max) => {
			return Math.random()*(max-min+1) + min
		}
		console.log(randoms(0,5))//->4.092803148616358



		/**
		 * 23
		 * 随机化数组的顺序
		 * 使用sort()重新排序元素
		 * 利用Math.random()来随机排序
		 */
		const shuffle = arr => arr.sort(()=> Math.random()-0.5);
		console.log(shuffle([1,2,3,4]))//-> 随机排序




		/**
		 * 24
		 * 反转一个字符串
		 * 使用数组结构和Array.reverse()来颠倒顺序
		 * 合并字符以使用join('')获取字符串
		 */
		const reverseString = str => [...str].reverse().join('');
		console.log(reverseString('foobar')) //->raboof



		/**
		 * 25
		 * 数组之间的相似性
		 * 使用filter（）移除不是values的一部分值
		 * 使用includes（）确定。
		 */
		const similarity = (arr,values) => {
			return arr.filter(v => values.includes(v));
		} 
		console.log(similarity([1,2,3], [1,2,4]))//->[1, 2]


		/**
		 * 26
		 * 按字符串排序（按字母顺序排列）
		 * 使用split('')分割字符串
		 * sort()使用localeCompare()
		 * 使用join('')重新组合
		 */
		const sortCharacter = str => {
			return str.split('').sort((a,b) => a.localeCompare(b)).join('');
		}
		console.log(sortCharacter('cabbage'))//->aabbceg


		/**
		 * 27
		 * 数组求和
		 * 使用reduce（）将每个值添加到累加器，
		 * 初始化值为0。
		 */
		const sum = arr => arr.reduce((acc,val) => acc + val, 0);
		console.log(sum([1,2,1,3,5])) //-> 12


		/**
		 * 28
		 * 交换两个变量的值
		 * 使用数组结构来交换两个变量之间的值
		 */
		//[varA,varB] = [varB,varA];
		// [x, y] = [y, x]
		



		/**
		 * 列表的tail
		 */
		const tail = arr => arr.length > 1 ? arr.slice(1) : arr;

		// tail([1,2,3]) -> [2,3]
		// tail([1]) -> [1]
		console.log(tail([1,2,3,4,5,7,4]))



		/**
		 * 30
		 * 数组去重
		 * 使用ES6 Set 和 rest
		 */
		const unique = arr => [...new Set(arr)];
		console.log(unique([1,"a","a",1,2,2,3,4,4,5]))
		// -> [1, "a", 2, 3, 4, 5]
		


		/**
		 * 31
		 * 验证数字
		 * 使用！isNaN 和 parseFloat() 检查参数是否是一个数字
		 * 使用isFinite() 来检查数字是否是有限的
		 */
		const validateNumber = n => {
			return !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;
		}
		console.log(validateNumber("10")) //-> true



		/**
		 *32
		 *URL参数
		 * 使用match()与适当的正则表达式来获取所有的键值对
		 * 适当的map()
		 * 使用Object.assign() 和spread运算符(...)
		 * 将所有的键值对组合到一个对象中
		 * 将location.search作为参数传递给当前url
		 */
		const getUrlParameters = url => {
			return url.match(/([^?=&]+)(=([^&]*))/g)
			.reduce((a,v) => (a[v.slice(0,v.indexOf('='))] = v.slice(v.indexOf('=')+1),a),{})
		}

		console.log(getUrlParameters('http://url.com/page?name=Adam&surname=Smith'))
		//-> {name: "Adam", surname: "Smith"}


	</script>
</body>
</html>